//------------------------------------------------------------------------------
// X2D Game Engine
// Copyright (C) 2006-2007 Janusz Kowalski
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------

#include "imgSDL.h"
#include "RawVector.h"

#ifndef X2D_BGLAYER_H
#define X2D_BGLAYER_H

// All the objects appear behind the camera.
// - Infinite distance ~ object attached to the camera.
// - Some finite distance behind the map.
// - Distance equal to the distance of the map.
// - Some finite distance in front of the map.

namespace x2d {

//-----------------------------------------------------------------------------
// BgScrap class
//-----------------------------------------------------------------------------

// For the scale = 1 object is at the distance of the screen, and when the
// screen moves up by n pixels, we can see such object moving by n pixels
// down.
// For the scale = 0 object is at infinite distance, and when the screen moves
// it remains still on the screen.

// Default scale for the objects at the map distance.
const double OP_MAP_DIST_SCALE = 0.02;
// Distance from the map to the screen [m].
const double OP_MAP_DIST_M = 5.88;
// Distance of the observer to the screen [m].
const double OP_OBSERVER_DIST_M = 0.12;
// Number of pixels per meter on the image of the map seen on the screen.
const int OP_MAP_PX_PER_M = 48;
// Number of pixels per meter of the screen.
const double OP_PX_PER_M = 2400.0;

class BgScrap {
  public:
    // The coordinates of the start position in pixels of the layer.
    int x_;
    int y_;
    // Scale factors are used when the layer is moved. They represent the ratio
    // of the movement seen on the screen to the real movement of an object.
    // (This scaling usually applies also to dimensions of the objects).
    double scaleX_;
    double scaleY_;
    // Distance (in pixels of the given layer) after which graphic will
    // be repeated. Should not be smaller than the dimensions of the graphic.
    int repeatX_;
    int repeatY_;
    // The image that all the BgScrap object is about.
    Image image_;
    // Create new BgScrap object.
    BgScrap(const char *path, int x, int y, double scale, int repeatX, int repeatY);
};

// Image with x and y coordinates.
class ImageXY : public Image {
  private:
    int x_;
    int y_;
  public:
    ImageXY(int x, int y, const char *path) : Image(path), x_(x), y_(y) { }
    inline int getX() {return x_;}
    inline int getY() {return y_;}
    ~ImageXY() { }
};

class BgLayer {
  private:
    // Vector?
    RawVector<ImageXY> imageList_;
    
    // Position.
    int x_;
    int y_;
    
    // Dimensions.
    int w_;
    int h_;
    
    // Relative displacement factors.
    // 0 - no movement (infinite distance)
    // (0,1) - movement slower than observation window (some distance)
    // 1 - the same speed as the observatiob point (distance of the map)
    // >1 - bigger speed than the observation point (closer than the map)
    double relX_;
    double relY_;
    
    // Repeating.
    bool repeatX_;
    bool repeatY_;
    
  public:
    BgLayer();
    ~BgLayer();
    
    // Returns the position of the beginning of the layer relative to
    // the given observation position. For example deltaX=-1 means that
    // the position of the layer is 1 pixel to the left from the observation
    // position.
    double getDeltaX(double x0);
    double getDeltaY(double y0);
    
    inline bool repeatX() {return repeatX_;}
    inline bool repeatY() {return repeatY_;}
    
    inline int getW() {return w_;}
    inline int getH() {return h_;}
    
    // We may also want to get list of the images on the layer.
    inline RawVector<ImageXY> *getImageList() {return &imageList_;}
};

} // namespace x2d

#endif
